<?php
/**
 * @author spenceryg
 * @date 2023/3/24
 * @time 12:06 下午
 * @focus love & life
 */


namespace app\api\controller;

use app\auto\model\Method;
use app\common\lib\ChatGpt;
use app\common\lib\Sensitive;
use app\common\model\ArticleClass;
use app\common\model\ArticleContent;
use app\common\model\MemberPointsLog;
use app\common\model\PushLog;
use GuzzleHttp\Client;
use hg\apidoc\annotation as Apidoc;
use hg\apidoc\annotation\Param;
use think\db\Raw;
use think\Exception;
use think\facade\Db;
use think\response\Json;

/**
 * Class Article
 * @package app\api\controller
 *
 * @Apidoc\Title("文章管理")
 * @Apidoc\Group("api")
 */
class Article extends Auth
{

    /**
     * addArticle
     * @Apidoc\Title("添加文章创作")
     * @Apidoc\Method("post")
     * @Apidoc\Param("articles",type="array",require=true,desc="文章标题数组")
     * @Apidoc\Param("type",type="int",require=true,desc="是否审核 0 自动审核 1 人工审核")
     * @Apidoc\Param("lang",type="String",require=true,desc="语言，默认为中文")
     * @Apidoc\Param("forbiddenwords_id",type="int",require=true,desc="伪禁词id")
     * @Apidoc\Param("article_class_id",type="int",require=true,desc="文章分类 ")
     * @Apidoc\Param("length",type="int",require=true,desc="文章字数 ")
     */
    public function addArticle()
    {
        /******************言论审查开始***********************************/
        //数据检验开始，这里审查用户的言论是否符合国家法律规定，这里一定要加上++++++++++++++++++++++++++++++++++++++++++++++++++++++
        $TextModeration=new \app\api\service\TextModerationService();
        if (!$TextModeration->check(json_encode($this->request->param(),JSON_UNESCAPED_UNICODE))) {
            return error($TextModeration->msg);
        }
        /*****************言论审查结束了**********************************/
        $member_id = $this->request->uid;
        $articles = input('articles', []);
        $lang = input('lang', '中文');
        $type = input('type');
        $img_class_id = input('img_class_id', '');
        $gpt_id = input('gpt_id', '');
        if(!$gpt_id){
            return error("请选择提示词");
        }
        $forbiddenwords_id = input('forbiddenwords_id',0);
        $article_class_id = input('article_class_id', 0, 'intval');
        if (!$article_class_id) {
            $article_class_id = ArticleClass::where('member_id', $member_id)->value('id');
        }
        $length = input('length', 2000, 'intval');

        $member = \app\common\model\Member::find($member_id);

        // 如果文章标题重复 直接删除掉 不会入库
        foreach ($articles as $index => $article) {
            $exist = \app\common\model\Article::where([
                'name' => $article,
                'member_id' => $member_id,
            ])->count();
            if($exist){
                unset($articles[$index]);
            }
        }
        // 积分验证
        $cost_points = sizeof($articles) * config('user.point_per_article');
        $member_point_num = $member['point_num'];
        if ($member_point_num > $cost_points ) {
            \app\common\model\Member::update([
                'id' => $member_id,
                'point_num' => $member_point_num - $cost_points
            ]);
        } else {
            return error('积分不足, 请充值积分！',['action' => 'recharge']);
        }

        $point_log = MemberPointsLog::create([
            'member_id' => $member_id,
            'num' => -1 * $cost_points,
            'end_num' => $member_point_num - $cost_points,
            'remarks' => "文章创作"
        ]);

        $ids_arr = [];
        foreach ($articles as $article) {
            $article = \app\common\model\Article::create([
                'name' => trim($article,"\""),
                'state' => 0,
                'lang' => $lang,
                'type' => $type,
                'member_id' => $member_id,
                'article_class_id' => $article_class_id,
                'forbiddenwords_id' => $forbiddenwords_id,
                'img_class_id' => $img_class_id,
                'gpt_id' => $gpt_id,
                'length'=>$length,
            ]);
            ArticleContent::create([
                'article_id' => $article->id,
                'name' => ''
            ]);
            $ids_arr[] = $article->id;
        }
        $point_log->associated_ids = implode(',', $ids_arr);
        $point_log->save();
        return success();
    }


    /**
     * list
     * @Apidoc\Title("文章列表")
     * @Apidoc\Query("state",type="int", require=true, desc="文章状态 0 创作中 1 待审核 2 待发布 3 已发布")
     * @Apidoc\Query("page",type="int", require=true, desc="第几页")
     * @Apidoc\Query("list_rows",type="int", require=true, desc="每页条数")
     * @Apidoc\Query("keywords",type="varchar", desc="搜索关键字 如果是数字的话搜索id")
     * @Apidoc\Query("class_id",type="int", desc="文章分类")
     */
    public function list()
    {
        $list_rows = input('list_rows', 10, 'intval');
        $where = [];
        $keywords = input('keywords', '', 'trim');
        if ($keywords) {
            if(is_numeric($keywords)){
                $where[] = ['id', '=',$keywords];
            }else{
                $where[] = ['name', 'like', '%' . $keywords . '%'];
            }

        }

        $class_id = input('class_id', 0, 'intval');
        if ($class_id) {
            $where[] = ['article_class_id', '=', $class_id];
        }

        $where[] = ['member_id', '=', $this->request->uid];

        $site_id = input('site_id');
        if($site_id) {
            $where[] = ['site_id', '=', $site_id];
        }


        $state = input('state', 0, 'intval');
        $order = 'id desc';
        if ($state == 0) {
            $list_rows = 100000;
            $order = 'id asc';
        }
        if ($state == 3||$state == 4) {
            $order = 'push_time desc';
        }        
        $where[] = ['state', '=', $state];
        $res = \app\common\model\Article::order($order)->where($where)->paginate($list_rows);
        $res = $res->toArray();
        
        foreach ($res['data'] as $index => $item) {
            //栏目信息
            $item['articleClass'] = Db::name("article_class")->find($item['article_class_id']);
            //如果是已发布返回站点信息
            if ($state == 3||$state == 4) {
                $item['site_name'] = Db::name("site")->where('id', $item['site_id'])->value('name');
                $item['push_time'] = date('Y-m-d H:i:s', $item['push_time']);
            }
            if ($state == 4) {
                $item['push_remarks'] = Db::name("push_log")->where('article_id', $item['id'])->order("create_time desc")->value('remarks');
            }            
            $res['data'][$index] = $item;
        }        


        $where_base = [];
        $where_base[] = ['member_id', '=', $this->request->uid];
        $count_0 = \app\common\model\Article::where($where_base)->where('state', 0)->count('id');
        $count_1 = \app\common\model\Article::where($where_base)->where('state', 1)->count('id');
        $count_2 = \app\common\model\Article::where($where_base)->where('state', 2)->count('id');
        $count_3 = \app\common\model\Article::where($where_base)->where('state', 3)->count('id');
        $count_4 = \app\common\model\Article::where($where_base)->where('state', 4)->count('id');

        $result[0] = $res;
        $result[1] = [$count_0, $count_1, $count_2, $count_3,$count_4];
        return success('ok', $result);
    }


    /**
     * getContent
     * @Apidoc\Title("获取文章内容")
     * @Apidoc\Query("id", type="int", desc="文章id")
     */
    public function getContent(): Json
    {
        $id = input('id');
        $content = ArticleContent::where('article_id', $id)->value('name');
        return success('ok', ['content' => $content]);
    }

    /**
     * editor
     * @Apidoc\Title("编辑文章")
     */
    public function editor(): Json
    {
        /******************言论审查开始***********************************/
        //数据检验开始，这里审查用户的言论是否符合国家法律规定，这里一定要加上++++++++++++++++++++++++++++++++++++++++++++++++++++++
        $TextModeration=new \app\api\service\TextModerationService();
        if (!$TextModeration->check(json_encode($this->request->param(),JSON_UNESCAPED_UNICODE))) {
            return error($TextModeration->msg);
        }
        /*****************言论审查结束了**********************************/
        $data = request()->post(['id', 'name', 'article_class_id', 'content', 'keywords']);
        validate([
            'id|编号' => 'require',
            'name|标题' => 'require',
            'article_class_id|栏目' => 'require',
            'content|文章内容' => 'require',
        ])->check($data);
        $article = \app\common\model\Article::find($data[id]);
        if ($article['member_id'] != $this->request->uid) {
            return error('非法请求！');
        }
        $data['name'] = Sensitive::replace($data['name']);
        \app\common\model\Article::update([
            'id' => $data['id'],
            'name' => $data['name'],
            'keywords' => $data['keywords'],
            'article_class_id' => $data['article_class_id']
        ]);
        $data['content'] = Sensitive::replace($data['content']);
        ArticleContent::where('article_id', $data['id'])->save([
            'name' => $data['content']
        ]);
        return success();
    }


    /**
     * delete
     * @Apidoc\Title("删除文章")
     */
    public function delete(): Json
    {
        $ids = input('ids');
        foreach ($ids as $id) {
            $article_member_id = \app\common\model\Article::where('id', $id)->value('member_id');
            if($article_member_id != $this->request->uid) {
                return error('非法请求！');
            }
        }
        \app\common\model\Article::destroy($ids);
        ArticleContent::destroy(function ($query) use ($ids) {
            $query->where('article_id', 'in', $ids);
        });
        return success($ids);
    }

    public function setPush(): Json
    {
        $ids = input('ids');
        foreach ($ids as $id) {
            $article_member_id = \app\common\model\Article::where('id', $id)->value('member_id');
            if($article_member_id != $this->request->uid) {
                return error('非法请求！');
            }else{
                \app\common\model\Article::where('id', $id)->update([
                    'state' => 3,
                    'push_time' => time(),
                ]);
            }
        }
        return success($ids);
    }
    /**
     * setChecked
     * @Apidoc\Title("批量设置已审核")
     * @Apidoc\Method("post")
     * @Apidoc\Param("ids",type="array",require=true,desc="文章id数组")
     */
    public function setChecked(): Json
    {
        $ids = input('ids');
        foreach ($ids as $id) {
            $article_member_id = \app\common\model\Article::where('id', $id)->value('member_id');
            if($article_member_id != $this->request->uid) {
                return error('非法请求！');
            }
        }
        \app\common\model\Article::where('id', 'in', $ids)->save([
            'state' => 2
        ]);
        return success();
    }
    
    /**
     * changeClass
     * @Apidoc\Title("转移文章分类")
     * @Apidoc\Method("post")
     * @Apidoc\Param("ids",type="array",require=true,desc="文章id数组")
     * @Apidoc\Param("article_class_id",type="int",require=true,desc="目标文章分类id")
     */
    public function changeClass(): Json
    {
        $data = request()->post(['ids', 'article_class_id']);
        validate([
            'ids|文章id' => 'require',
            'article_class_id|目标分类' => 'require',
        ])->check($data);
        foreach ($data['ids'] as $id) {
            $article_member_id = \app\common\model\Article::where('id', $id)->value('member_id');
            if($article_member_id != $this->request->uid) {
                return error('非法请求！');
            }
        }
        \app\common\model\Article::where('id', 'in', $data['ids'])->save([
            'article_class_id' => $data['article_class_id']
        ]);
        return success();
    }
    /**
     * setReadpush
     * @Apidoc\Title("将文章设为待发布")
     * @Apidoc\Method("post")
     * @Apidoc\Param("ids",type="array",require=true,desc="文章id数组")
     */
    public function setReadpush(): Json
    {
        $data = request()->post(['ids']);
        validate([
            'ids|文章id' => 'require',
        ])->check($data);
        foreach ($data['ids'] as $id) {
            $article_member_id = \app\common\model\Article::where('id', $id)->value('member_id');
            if($article_member_id != $this->request->uid) {
                return error('非法请求！');
            }
        }
        \app\common\model\Article::where('id', 'in', $data['ids'])->save([
            'state' => 2
        ]);
        return success();
    }    
    /**
     * push2
     * @Apidoc\Method("post")
     * @Param("id", type="int", desc="id",require=true)
     * @Param("site_id", type="int", desc="site_id",require=true)
     * @Param("site_class_id", type="int", desc="site_class_id",require=true)
     * @Param("is_insert_img", type="int", desc="is_insert_img",require=true)
     * @Param("img_class_id", type="int", desc="img_class_id",require=true)
     * @Param("img_line", type="int", desc="图片插入段落的位置：0为随机，1为第一段前，n为第n段前，当n大于段落数则会插入到文章末尾（建议要放到最后一行可以设置为100）",require=true)
     * @Param("is_relation", type="int", desc="开启文章关联",require=true)
     * @Param("relation_num", type="int", desc="关联文章条数",require=true)
     * @Param("relation_title", type="int", desc="相关文章的标题",require=true)
     * @Apidoc\Title("文章发布")
     */
    public function push2()
    {
        $data = request()->post([
            'id', 'site_id', 'site_class_id', 'is_insert_img', 'img_class_id', 'img_line', 'is_relation', 'relation_num', 'relation_title'
        ]);
        validate([
            'id|文章id' => 'require',
            'site_id|网站' => 'require',
            'site_class_id|网站栏目' => 'require',
        ])->check($data);
        foreach ($data['ids'] as $id){
            $article_member_id = \app\common\model\Article::where('id', $id)->value('member_id');
            if($article_member_id != $this->request->uid) {
                return error('非法请求！');
            }
        }
        if($data['is_insert_img']&&!$data['img_class_id']){
             return error('请选择图片分类！');
        }        
        if($data['is_relation']&&!$data['relation_title']){
             return error('自定义相关文章标题不能为空！');
        }

        
        $s=new \app\api\service\ArticlePushService([
            "article_id"=>$data['id'],//要发布的文章id
            "site_id"=>$data['site_id'],//目标站点id
            "site_cat_id"=>$data['site_class_id'],//目标站点的栏目id
            "insert_picture_class"=>$data['img_class_id'],//文章要调用的图片分类id
            "insert_picture_line"=>$data['img_line'],//图片插入段落的位置：0为随机，1为第一段前，n为第n段前，当n大于段落数则会插入到文章末尾（建议要放到最后一行可以设置为100）
            "relation_article_num"=>$data['relation_num'],//查询关联的文章数量
            "relation_article_str"=>$data['relation_title']//在文章中插入相关文章的标题，默认为：相关文章
        ]);
        $s->getArticle();//查询文章
        $s->getSite();//查询站点
        $s->getSiteLink();//查询站点锚链接
        $s->repArticleKeywords();//替换文章中的关键词为站点里的词库
        $s->repSiteLink();//替换文章中的关键词锚链接
        //文章中插入图片
        if($s->insert_picture_class){
            $s->insertArticlePicture();
        }   
        //文章内容增加相关文章
        if($s->relation_article_num){
            $s->setRelationArticle();
        }
        //获取发送的数据参数，返回值为array[data,cookies,headers,url,flag]
        $pushParam=$s->getPushFormData();

        //开始发送
        $result=$s->push($pushParam);
        if($result['status']){
            //发布成功
            $s->updateArticle($s::successState, $result['article_url']);//更新文章状态
            $s->addPushLog(1,$result['msg']);//增加发布日志
            return success($result['msg'],1);
        }else{
            //发布失败
            $s->updateArticle($s::errorState);//更新文章状态
            $s->addPushLog(0,$result['msg']);//增加发布日志
            return success($result['msg'],0);
        }
    }

    /**
     * push
     * @Apidoc\Method("post")
     * @Param("ids", type="int", desc="ids",require=true)
     * @Param("site_id", type="int", desc="site_id",require=true)
     * @Param("site_class_id", type="int", desc="site_class_id",require=true)
     * @Param("is_insert_img", type="int", desc="is_insert_img",require=true)
     * @Param("img_class_id", type="int", desc="img_class_id",require=true)
     * @Apidoc\Title("文章发布")
     */
    public function push()
    {
        $data = request()->post([
            'ids', 'site_id', 'site_class_id', 'is_insert_img', 'img_class_id'
        ]);
        validate([
            'ids|文章id' => 'require',
            'site_id|网站' => 'require',
            'site_class_id|网站栏目' => 'require',
        ])->check($data);
        foreach ($data['ids'] as $id){
            $article_member_id = \app\common\model\Article::where('id', $id)->value('member_id');
            if($article_member_id != $this->request->uid) {
                return error('非法请求！');
            }
        }
        $total = 0;
        $success = 0;
        $fail = 0;
        foreach ($data['ids'] as $id) {
            $req = $this->getPushFormData($id, $data['site_id'], $data['site_class_id'], $data['is_insert_img'], $data['img_class_id']);
            $res = $this->sendPush($req);
            if ($res) {
                $success++;
            } else {
                $fail++;
            }
            $total++;
        }
        return success('', [
            'total' => $total,
            'success' => $success,
            'fail' => $fail
        ]);
    }


    private function sendPush($data)
    {
        try {
            $res = (new Client())->post($data['url'], [
                'form_params' => $data['form'],
                'headers' => $data['headers']
            ]);
            $res = $res->getBody()->getContents();
            if (strpos($res, $data['flag']) !== false) {
                \app\common\model\Article::update([
                    'id' => $data['article_id'],
                    'state' => 3,
                    'push_time' => date('y-m-d H:i:s', time()),
                    'site_id' => $data['site_id'],
                ]);
                \app\common\model\Site::update([
                    'id' => $data['site_id'],
                    'today_quantity' => Db::raw('today_quantity+1'),
                    'cumulative_quantity' => Db::raw('cumulative_quantity+1'),
                ]);
                PushLog::create([
                    'state' => 1,
                    'member_id' => $data['member_id'],
                    'article_id' => $data['article_id'],
                    'push_plan_id' => 0,
                    'site_id' => $data['site_id'],
                    'site_catid' => $data['site_catid'],

                ]);
                return true;

            } else {
                PushLog::create([
                    'state' => 0,
                    'member_id' => $data['member_id'],
                    'article_id' => $data['article_id'],
                    'site_id' => $data['site_id'],
                    'site_catid' => $data['site_catid'],
                    'remarks' => '返回值无成功标志。'. $res
                ]);
                return false;
            }
        } catch (\Exception $e) {
            PushLog::create([
                'state' => 0,
                'member_id' => $data['member_id'],
                'article_id' => $data['article_id'],
                'site_id' => $data['site_id'],
                'site_catid' => $data['site_catid'],
                'remarks' => '网络请求错误。'. $e->getMessage()
            ]);
            return false;
        }

    }


    private function getPushFormData($id, $site_id, $site_class_id, $is_insert_img, $img_class_id)
    {
        $article = \app\common\model\Article::find($id);
        $site = \app\common\model\Site::find($site_id);
        $siteLink = \app\common\model\SiteLink::where("site_id","=",$site_id)->select();

        $form_data = [];
        $form_data[$site['column_field']] = $site_class_id;
        $form_data[$site['article_content_field']] = $article->articleContent->name;
        $form_data[$site['create_time_field']] = date('y-m-d H:i:s', time());
        $form_data[$site['title_field']] = $article->name;
        $form_data['key'] = $site['secret_key'];
        $url = $site['website'] . $site['publishing_interface'];
        $split_flag = '?';
        if(strpos($url,'?')!==false){
            $split_flag = '&';
        }
        $url = ($site['is_https'] ? 'https://' : 'http://') . $url .$split_flag  .'key=' . $site['secret_key'];
        //锚链接替换
        if($siteLink){
            foreach ($siteLink as $link) {
                $patten = '/(?<!href=")(?<!alt=")' .$link['name']. '(?!<\/a>)(?<!\/>)/';
                // 对锚链接在标签中和图片 alt 属性的判断
                $form_data[$site['article_content_field']] = preg_replace($patten,'<a href="'.$link['url'].'" target="_blank">' . $link['name'] . '</a>', $form_data[$site['article_content_field']],1);
            }
        }
        //是否插入图片
        if ($is_insert_img) {
            $img = \app\common\model\MemberFile::order('update_time', 'asc')->where('img_class_id', $img_class_id)->find();
            if ($img) {
                $form_data[$site['thumbnail_field']] = $img['filepath'];
                $form_data[$site['article_content_field']] = '<p style="text-align: center;"><img src="' . $img['filepath'] . '"></p>' . $form_data[$site['article_content_field']];
                $img->force()->save();
            }
        }



        if ($site['other_fields']) {
            $other_fields = explode("\n", $site['other_fields']);
            foreach ($other_fields as $field) {
                $field = trim($field, "\r");
                if (strstr($field, ':')) {
                    [$key, $val] = explode(':', $field);
                    //替换相关标签
                    $val=repPushOtherLib($val);                 
                    $form_data[$key] = $val;
                }
            }
        }

        $cookies = [];
        if ($site['cookies']) {
            $other_fields = explode("\r\n", $site['cookies']);
            foreach ($other_fields as $field) {
                if (strstr($field, ':')) {
                    [$key, $val] = explode(':', $field);
                    $cookies[$key] = $val;
                }
            }
        }


        $headers = [];
        if ($site['headers']) {
            $other_fields = explode("\r\n", $site['headers']);
            foreach ($other_fields as $field) {
                if (strstr($field, ':')) {
                    [$key, $val] = explode(':', $field);
                    $headers[$key] = $val;
                }
            }
        }

        return [
            'member_id' => $article['member_id'],
            'article_id' => $id,
            'form' => $form_data,
            'cookies' => $cookies,
            'headers' => $headers,
            'url' => $url,
            'flag' => $site['publish_success_flag'],
            'site_id' => $site_id,
            'site_catid' => $site_class_id
        ];
    }


    /**
     * getEditor
     * @Apidoc\Title("获取文章编辑内容")
     */
    public function getEditor()
    {
        $id = input('id');
        $article_member_id = \app\common\model\Article::where('id', $id)->value('member_id');
        if ($article_member_id != $this->request->uid) {
            return error('非法请求！');
        }
        $article = \app\common\model\Article::with('articleContent')
            ->where('member_id', $this->request->uid)
            ->where('id', $id)->find();
        $res = [
            'id' => $id,
            'name' => $article->name,
            'article_class_id' => $article['article_class_id'],
            'content' => $article->articleContent->name,
            'keywords' => $article->keywords
        ];
        return success('', $res);

    }


    /**
     * getRecentCreatedArticles
     * @Apidoc\Title("获取最近10秒内创作的文章id")
     */
    public function getRecentCreatedArticles()
    {

//        $res = ArticleContent::hasWhere('article', ['member_id'=>$this->request->uid])
       $res = Db::table('db_article_content')->join('db_article', 'db_article.id=db_article_content.article_id')
            ->where('db_article.member_id', $this->request->uid)
        ->where('db_article_content.update_time', '>' , time() - 60)
            ->where('db_article_content.update_time!=db_article_content.create_time')
            ->column('db_article_content.article_id');
        return success('', $res);
    }
}
